﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;


namespace Game_Engine
{
    public class Transform
    {
        private Vector3 localScale;
        private Quaternion localRotation;
        private Vector3 localPosition;
        private Matrix world;
        private Transform parent;
        private List<Transform> Children { get; set; }

        private void UpdateWorld()
        {
            world = Matrix.CreateScale(localScale) *
                    Matrix.CreateFromQuaternion(localRotation) *
                    Matrix.CreateTranslation(localPosition);

            if (parent != null)
                world = world * parent.World;

            foreach (Transform child in Children)
                child.UpdateWorld();
        }

        //We must wrap private members in public properties so that after calling Set on a property, we can UpdateWorld() immediately.
        //We need local variables to use in UpdateWorld(), because updating needs to occur immediately after Set, yet within the Set block
        public Transform Parent
        {
            get { return parent; }
            set {
                    if (value == this)
                        return;

                    if (parent != null)
                        parent.Children.Remove(this);
                    parent = value;
                    if (parent != null)
                        parent.Children.Add(this);
                    UpdateWorld();
                }
        }
        public Vector3 LocalScale
        {
            get { return localScale; }
            set { localScale = value; UpdateWorld(); }
        }

        public Quaternion LocalRotation
        {
            get { return localRotation; }
            set { localRotation = value; UpdateWorld(); }
        }

        public Vector3 LocalPosition
        {
            get { return localPosition; }
            set{localPosition = value; UpdateWorld(); }
        }

        public Vector3 Position
        {
            get { return world.Translation; }
        }

        public Matrix World
        {
            get { return world; }
        }

        public Vector3 Forward
        {
            get { return World.Forward; }
        }

        public Vector3 Left
        {
            get { return World.Left; }
        }

        public Vector3 Up
        {
            get { return World.Up; }
        }

        public Transform()
        {
            Children = new List<Transform>();
            parent = null;
            localScale = Vector3.One;
            localRotation = Quaternion.Identity;
            localPosition = Vector3.Zero;
            UpdateWorld();
        }

        public void Rotate(Vector3 axis, float angle)
        {
            LocalRotation = Quaternion.CreateFromAxisAngle(axis, angle) * LocalRotation; //Post multiplication updates our Left, Up, Forward vectors
        }

        
    }
}
